package com.ykht.proj.activity.utils.wx;


import cn.hutool.core.codec.Base64;
import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.ykht.proj.activity.entity.CnActivityOrder;
import com.ykht.proj.activity.entity.VOrder;
import com.ykht.proj.coupon.entity.CnPerson;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;


@Slf4j
public class WxPayutil {


	// 你的商户私钥
	private static String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
			"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDW9vDgv7BULI7C\n" +
			"UgJgcgmWl2EZSZJU485bPaJkGcsTRESzAr2WkHd6WKCtZzB6hSHBMs4TGKhclGQ0\n" +
			"PVriRld3PtueyHFTeYwieaW/YJ94jS/6DsMSFOdmGP2gwpiQZrbwSC29jN3df4p1\n" +
			"iNuSq+JfPgWH8G7Z95UIKxfGb3Rrr0JGav6GYezd1hV4Ngb798KVVhxGZB63UoiQ\n" +
			"NAdbZ9kSsukGaibOYicTRp76S7TF46yHt/z1MiqMI0xSEX+R+lVupukSrCA/n0TE\n" +
			"50bGtSnVoihTgh4JZNyIDejhMu3re41DPo2AcdV12taQKJS+vJC/oJZUr7j1v05I\n" +
			"R2yYC7dHAgMBAAECggEATmjaqhAhoEJ0fDrvtQBDsRNcjp3Aa4iAv9U2g67I3Sk8\n" +
			"qdMpFl9xxUXIrheCnl4rVs5STrLizoouFsP+f6TKyKs77qoMdDdUv0qCA9GZuZ4+\n" +
			"TsbNrq3DTgF1mgsBHULqHbEmRgq47s9T0NVvygs6UiVMXS59MLJXQRh+3pnO7Gvg\n" +
			"30u2iPBZoQttoyojTZktC6TQjVuj74b+OmvjIf85mHIZ2zdSnbtODjsuh/hYHIjh\n" +
			"idAYOmYHQ9MkVniwLjY6J26EEVyxoqIzkBot0rVi9flDwx8EzilR9aeyFnaapqva\n" +
			"HWRFmiI4zuenk8XzjBTox2Cbbsi1Q617UXBdaL6iuQKBgQDwggHm1aMvnm2DyQVx\n" +
			"Dcn5gSq5xC9ZiXN/xAXYyDcww7L5ClQOkXK5eIx3ZaYVZkAcWkyM0by72pfkOd53\n" +
			"ZNC29mn0aijbYHXj1sS9p3Wi2Of/dEE9rFZ3yy4e4LuZ7uF2m6BTPznUD4YDKnhh\n" +
			"BMu0XhcHql9ZJ+kqV6kMY8PvkwKBgQDkz7lF51oOrNU/fGjrxuoQsTKndl7dSJHV\n" +
			"3GHIbudpcHKIJXQXAYL1WL8CI+HGQmy4qTLqSpu4i3VziTN2ypTSzvlrRegFFceS\n" +
			"Glr5IRk8OTLledHQRs0sju+eq9ixjzxSgUwDolzNaqchYv6hurp7VRxWcET1NnH9\n" +
			"RTZ/5CIh/QKBgGoxbTeIMwKOmFptAwsVBI43Oy9E8Yc+SpIqck5ysPPGJRsTNWQt\n" +
			"UpOUJ6l8Z2XhfQNH168B2Ky1awWpi5H6ILH4gXYa/alHoSYVqU74Rte9oEpKAZiC\n" +
			"pLdGLjoSDqN8N28QbizzqMv6griZIwfrfypHtTF8R5dtKOW6SPkgf94jAoGBAM3m\n" +
			"u6PTJ/ByyUdjDgu2KWWx/5JA6+cXadzYf8ndOzNf9EDd61TUkGN2ZBRp8770gV+/\n" +
			"Ksk5MF5maN/6RCyO6lO12y8UblE9IyUvwFPV3B6cnldwQ0W4oOOLEMhpfgtyiOb5\n" +
			"4UyX7AkSA6oAqoEhRrS7h0+lofhD8Vnn0b5OrgSFAoGBALxJ+O2G0HUu5waBWI82\n" +
			"PX117bWE4QB7poOJKPqrBT3WGjVbWM66zbZPhA3GJ3b5bdNkrXQm801puN0orhKu\n" +
			"ScNl6gDd2RTIkLQr7+fP8gx8DtXpssqXaCmyj/o48w0Ek8dznpY5NFek/4mssLxw\n" +
			"qNL1lWO6d7qXFD7L92pEyvxU\n" +
			"-----END PRIVATE KEY-----\n";

	// 你的微信支付平台证书
	private static String certificate =  "-----BEGIN CERTIFICATE-----\n" +
			"MIID3DCCAsSgAwIBAgIUJGmFyT1xF5PTTVb4xSN5Ud+gXiAwDQYJKoZIhvcNAQEL\n" +
			"BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT\n" +
			"FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg\n" +
			"Q0EwHhcNMjEwMTA0MDk0MTAzWhcNMjYwMTAzMDk0MTAzWjBuMRgwFgYDVQQDDA9U\n" +
			"ZW5wYXkuY29tIHNpZ24xEzARBgNVBAoMClRlbnBheS5jb20xHTAbBgNVBAsMFFRl\n" +
			"bnBheS5jb20gQ0EgQ2VudGVyMQswCQYDVQQGDAJDTjERMA8GA1UEBwwIU2hlblpo\n" +
			"ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC63kASrCvb6CMYIpPW\n" +
			"BCrtIj80SYBICfWb2hdpB7TUZ8w9bqp/GQcoQF++xvYiMmqZheEdKFi4ebgZV2Da\n" +
			"dbMMjS+YcLr/LYFUNSaTwprPcNA3RC44k5uN8VqhDpLlVOh1DXj/CHXBp6zeUw/f\n" +
			"f9XFhjt6lMcZngeDcKd7KdX0YNYeUOfXkeQWGJqZGu4dQbWxp5EiBEYPD4hA1aDf\n" +
			"DTWRhuxrkM7815tIefIe/kX38AqVgVScALqK6B2ANXL+VlPSd7lWUDHixRoP9uy/\n" +
			"Umb3MnlbvTX/emNQZtHL8/Psb1x0M+wHNGfqeu5Yk/7NFojYJRXIz4KPKQkJm6oC\n" +
			"1zuBAgMBAAGjgYEwfzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBlBgNVHR8EXjBc\n" +
			"MFqgWKBWhlRodHRwOi8vZXZjYS5pdHJ1cy5jb20uY24vcHVibGljL2l0cnVzY3Js\n" +
			"P0NBPTFCRDQyMjBFNTBEQkMwNEIwNkFEMzk3NTQ5ODQ2QzAxQzNFOEVCRDIwDQYJ\n" +
			"KoZIhvcNAQELBQADggEBAGyHQ9cBw8S25GdiPUw9oUNOxMafndmOf6NDValqPini\n" +
			"82VhakVFILC1T6DtenKOylb7rMiHwANbILRwTg/zxefOryzm1Hb77kWHn2ATOHw8\n" +
			"QlIYdbWWIQQRRXAfOodBy5EpDLc5mJRrtx3CkMkXG6dqxZ6fzFSG8s0BMXf/Rl1N\n" +
			"tbAwceaZrDVa34mCYC38gnC2W6CPmEbw8WtBHqs0UPDhs00UOqpz0YvNI/9n96JS\n" +
			"26At/uVjB+rhKXuYJkW3OxQCbTAurzFlddkgygB+x8yUrEBWaPAvv1nB7/c29Kmo\n" +
			"Od+oFWb6ogYxVoj61ZYQBDkY37qFnYfTelnYWJQop/0=\n" +
			"-----END CERTIFICATE-----";



	/**
	 * 统一下单
	 *
	 * @param conf
	 * @param person
	 * @return
	 * @throws UnsupportedEncodingException
	 */

	public static String v3PayTransactionsJsapi(WxPayProperties conf, CnPerson person, CnActivityOrder actOrder) throws UnsupportedEncodingException {
		log.info("->构建统一下单请求");
		List<X509Certificate> certificates  = new ArrayList<>();
		certificates.add(PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8"))));
		try (CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
				.withMerchant(conf.getMerchantId(), conf.getSerialNo(), PemUtil.loadPrivateKey(
						new ByteArrayInputStream(privateKey.getBytes("utf-8"))))
				.withWechatpay(certificates).build()){

			JSONObject order = new JSONObject();
			order.putOpt("appid",conf.getAppid());//应用ID
			order.putOpt("mchid",conf.getMerchantId());//直连商户号
			order.putOpt("description",actOrder.getActivityName());//商品描述
			order.putOpt("out_trade_no",actOrder.getOrderNumber());//商户订单号
//			order.putOpt("time_expire", LocalDateTime.now().plusMinutes(2)+"+08:00");//交易结束时间(非必填)
//			order.putOpt("attach",actOrder.getId().toString());//附加数据(非必填)
//			order.putOpt("goods_tag","");//订单优惠标记(非必填)
			order.putOpt("notify_url",conf.getNotify_url());//通知地址

			JSONObject amount = new JSONObject();//订单金额信息
			//
			amount.putOpt("total",actOrder.getPayAmount().multiply(new BigDecimal(100)).intValue());//int 订单总金额，单位为分
			JSONObject payer = new JSONObject();//支付者信息
			payer.putOpt("openid",person.getOpenId());//用户在直连商户appid下的唯一标识。
			order.putOpt("amount",amount);//金额
			order.putOpt("payer",payer);
			log.info("->组装body:{}",order);

			//统一下单地址
			String tyxdUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
//			String tyxdUrl = conf.getTyxdUrl();

			// ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

			// 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签
			HttpPost httpPost = new HttpPost(tyxdUrl);
			StringEntity reqEntity = new StringEntity(order.toString());
			httpPost.setEntity(reqEntity);
			httpPost.addHeader("Accept", "application/json");
			httpPost.addHeader("Content-Type", "application/json");
			log.info("->发送请求:{}",httpPost);
			CloseableHttpResponse response = httpClient.execute(httpPost);
			String result = null;
			log.info("->响应结果：{}",response.getEntity());
			if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
				result = EntityUtils.toString(response.getEntity());// 返回json格式：
				log.info("微信支付V3 url={} result={} ",tyxdUrl,result);

			}else {
				result = EntityUtils.toString(response.getEntity());// 返回json格式：
//					log.info("微信支付V3 url={} result={} response.getEntity()={}",url,result, JSON.toJSONString(response.getEntity()));
				log.info(result);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}
	public static String v3PayTransactionsJsapi_V2(WxPayProperties conf, CnPerson person, VOrder temp) throws UnsupportedEncodingException {
		log.info("->构建统一下单请求");
		List<X509Certificate> certificates  = new ArrayList<>();
		certificates.add(PemUtil.loadCertificate(new ByteArrayInputStream(certificate.getBytes("utf-8"))));
		try (CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
				.withMerchant(conf.getMerchantId(), conf.getSerialNo(), PemUtil.loadPrivateKey(
						new ByteArrayInputStream(privateKey.getBytes("utf-8"))))
				.withWechatpay(certificates).build()){

			JSONObject order = new JSONObject();
			order.putOpt("appid",conf.getAppid());//应用ID
			order.putOpt("mchid",conf.getMerchantId());//直连商户号
			order.putOpt("description","嗨吃卡");//商品描述
			order.putOpt("out_trade_no",temp.getOrderCode());//商户订单号
//			order.putOpt("time_expire", LocalDateTime.now().plusMinutes(2)+"+08:00");//交易结束时间(非必填)
//			order.putOpt("attach",actOrder.getId().toString());//附加数据(非必填)
//			order.putOpt("goods_tag","");//订单优惠标记(非必填)
			order.putOpt("notify_url",conf.getNotify_url());//通知地址

			JSONObject amount = new JSONObject();//订单金额信息
			//
			amount.putOpt("total",temp.getPayAmount().multiply(new BigDecimal(100)).intValue());//int 订单总金额，单位为分
			JSONObject payer = new JSONObject();//支付者信息
			payer.putOpt("openid",person.getOpenId());//用户在直连商户appid下的唯一标识。
			order.putOpt("amount",amount);//金额
			order.putOpt("payer",payer);
			log.info("->组装body:{}",order);

			//统一下单地址
			String tyxdUrl = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
//			String tyxdUrl = conf.getTyxdUrl();

			// ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

			// 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签
			HttpPost httpPost = new HttpPost(tyxdUrl);
			StringEntity reqEntity = new StringEntity(order.toString());
			httpPost.setEntity(reqEntity);
			httpPost.addHeader("Accept", "application/json");
			httpPost.addHeader("Content-Type", "application/json");
			log.info("->发送请求:{}",httpPost);
			CloseableHttpResponse response = httpClient.execute(httpPost);
			String result = null;
			log.info("->响应结果：{}",response.getEntity());
			if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
				result = EntityUtils.toString(response.getEntity());// 返回json格式：
				log.info("微信支付V3 url={} result={} ",tyxdUrl,result);

			}else {
				result = EntityUtils.toString(response.getEntity());// 返回json格式：
//					log.info("微信支付V3 url={} result={} response.getEntity()={}",url,result, JSON.toJSONString(response.getEntity()));
				log.info(result);
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

	}

	public static JSONObject toSign(WxPayProperties conf,String prepay_id) throws UnsupportedEncodingException {
		JSONObject data = new JSONObject();
		String appId = conf.getAppid();
		data.putOpt("appId",appId);//小程序id
		long timeStamp = System.currentTimeMillis()/1000;
		String nonceStr = UUID.randomUUID().toString().replaceAll("-","");
		data.putOpt("timeStamp",timeStamp);//当前的时间，其他详见时间戳规则。示例值：1414561699
		data.putOpt("nonceStr",nonceStr);//随机字符串，不长于32位。推荐随机数生成算法。

		prepay_id = "prepay_id="+prepay_id;

		data.putOpt("package",prepay_id);//统一下单接口返回的prepay_id参数值，提交格式如：prepay_id=***
		data.putOpt("signType","RSA");//签名类型，默认为RSA，仅支持RSA
		String tempSign = appId+"\n"+timeStamp+"\n"+nonceStr+"\n"+prepay_id+"\n";
		log.info("{}",tempSign);
		PrivateKey privateKeyTemp  =  PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
		Sign sign = SecureUtil.sign(SignAlgorithm.SHA256withRSA,Base64.encode(privateKeyTemp.getEncoded()),null);
		String base64Sign = Base64.encode(sign.sign(tempSign.getBytes()));
		data.putOpt("paySign",base64Sign);//签名，使用字段appId、timeStamp、nonceStr、package按照签名生成算法计算得出的签名值
		return data;
	}

}
